package mh.demo.calcite;

import mh.demo.calcite.utils.ResultSetUtil;
import org.apache.calcite.adapter.java.ReflectiveSchema;
import org.apache.calcite.jdbc.CalciteConnection;
import org.apache.calcite.schema.Schema;
import org.apache.calcite.schema.SchemaPlus;

import java.sql.*;
import java.util.Properties;

public class JavaSchemaDemo {

    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        Class.forName("org.apache.calcite.jdbc.Driver");
        Properties info = new Properties();
        info.setProperty("lex", "JAVA");
        info.setProperty("caseSensitive", "false");
        Connection connection = DriverManager.getConnection("jdbc:calcite:", info);
        CalciteConnection calciteConnection = connection.unwrap(CalciteConnection.class);
        SchemaPlus rootSchema = calciteConnection.getRootSchema();
        Schema schema = new ReflectiveSchema(buildHrSchema());
        rootSchema.add("hr", schema);
        Statement statement = calciteConnection.createStatement();
        ResultSet resultSet = statement.executeQuery(
                """ 
                        select d.deptno, min(e.empid)
                        from hr.emps as e
                        join hr.depts as d on e.deptno = d.deptno
                        group by d.deptno
                        having count(*) > 1
                        """);
        System.out.println(ResultSetUtil.resultString(resultSet));
        resultSet.close();
        statement.close();
        connection.close();
    }

    private static HrSchema buildHrSchema() {
        Employee[] emps = {new Employee(1L, 11L), new Employee(2L, 12L), new Employee(3L, 12L)};
        Department[] depts = {new Department(11L), new Department(12L)};
        return new HrSchema(emps, depts);
    }

    public static class HrSchema {
        public final Employee[] emps;
        public final Department[] depts;

        public HrSchema(Employee[] emps, Department[] depts) {
            this.emps = emps;
            this.depts = depts;
        }

    }

    public static class Employee {
        public final Long empId;
        public final Long deptNo;

        public Employee(Long empId, Long deptNo) {
            this.empId = empId;
            this.deptNo = deptNo;
        }
    }

    public static class Department {
        public final Long deptNo;

        public Department(Long deptNo) {
            this.deptNo = deptNo;
        }
    }

}
